﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Threading;

namespace de.codingfreaks.libs.cfDateTime
{
    /// <summary>
    /// Defines extension-methods for dealing with dates and times.
    /// </summary>
    public static class Extensions
    {

        #region extensions for int

        /// <summary>
        /// Calculates the last day of a month.
        /// </summary>
        /// <example>DateTime dtmFebruaryLast = 2.GetLastDayOfMonth(2010);</example>
        /// <param name="intMonth">The month of the day.</param>
        /// <param name="intYear">The year of the day.</param>        
        /// <returns>The <c>DateTime</c> of the last day.</returns>
        public static DateTime LastDayOfMonth(this int intMonth,
                                              int intYear)
        {
            intMonth++;
            if (intMonth > 12)
            {
                intMonth = 1;
                intYear++;
            }
            return new DateTime(intYear, intMonth, 1).AddDays(-1);
        }

        #endregion

        #region extensions for DateTime

        /// <summary>
        /// ISO 8601 implementation of the calculation for the week-number of a given
        /// date.
        /// </summary>
        /// <remarks>
        /// <ul>
        /// Assumes that
        /// <li>a week starts on a monday</li>
        /// <li>week #1 of a year is the one with the first thursday</li>
        /// </ul>
        /// <para>Example based on the code at http://codebetter.com/blogs/peter.van.ooijen/archive/2005/09/26/132466.aspx.</para>
        /// </remarks>
        /// <param name="dtmThis">The date for which to calculate the week-number.</param>
        /// <returns>The week number.</returns>
        public static int WeekOfYear(this DateTime dtmThis)
        {
            DateTime dtmStart = dtmThis.AddDays(- dtmThis.Day + 1).AddMonths(- dtmThis.Month + 1);
            // Get dec 31st of the year
            DateTime dtmEnd = dtmStart.AddYears(1).AddDays(-1);
            // ISO 8601 weeks start with Monday
            // The first week of a year includes the first Thursday
            // DayOfWeek returns 0 for sunday up to 6 for saturday            
            int[] aintCorrection = { 6, 7, 8, 9, 10, 4, 5 };
            int intDaySpanComplete = dtmThis.Subtract(dtmStart).Days + aintCorrection[(int)dtmStart.DayOfWeek];
            int intWeek = intDaySpanComplete / 7;
            switch (intWeek)
            {
                case 0:
                    // Return weeknumber of dec 31st of the previous year
                    return WeekOfYear(dtmStart.AddDays(-1));
                case 53:
                    // If dec 31st falls before thursday it is week 01 of next year
                    if (dtmEnd.DayOfWeek < DayOfWeek.Thursday)
                        return 1;
                    else
                        return intWeek;
                default:
                    return intWeek;
            }
        }

        #endregion

    }
}
